#ifndef __KEY_MANAGE_H__
#define __KEY_MANAGE_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "key_driver.h"
#include <string.h>

#define __KEY_EVENT_CALL(event)                 \
    do {                                        \
        if (key->event_callback[event]) {       \
            key->event_callback[event](key);    \
        }                                       \
    } while (0U)


#define CHECK_TICK                      5                      // 按键状态机检查间隔时间(ms)   
#define DEBOUNCE_TICK                   (15 / CHECK_TICK)      // 消抖时间(ms) [最大40/5且DEBOUNCE_TICK < SHORT_PRESS_START_TICK/2]
#define SHORT_PRESS_START_TICK          (300  / CHECK_TICK)    // 连击态触发间隔时间(ms) [最大40 / 5]
#define LONG_PRESS_START_TICK           (1000 / CHECK_TICK)    // 长按态触发时间(ms) 
#define LONG_HOLD_CYCLE_TICK            (500 / CHECK_TICK)     // 长按态保持下连续触发长按事件的间隔(ms) 

/**
 * @brief   按键对象状态
 */
enum key_state {
    Init_None_State = 0,        /* 初始未按下状态 */
    Init_Press_State,           /* 初次按下状态 */
    Press_Check_State,          /* 连击检查状态 */
    Continuous_Press_State,     /* 连续按下状态 */
    Long_Press_State,           /* 长按状态 */
};

/**
 * @brief   按键对象事件
 */
enum key_event { 
    Press_Down = 0,             /* 按键按下，每次按下都触发 */
    Press_Up,                   /* 按键弹起，每次松开都触发 */
    Singe_Click,                /* 单击触发(仅触发一次) */
    Double_Click,               /* 双击触发(仅触发一次) */
    Short_Press_Repeat,         /* 每次短按时都会触发(按下次数>=2) */
    Long_Press_Start,           /* 首次进入长按状态触发(仅触发一次) */
    Long_Press_Hold,            /* 长按保持状态触发(每经过一个循环长按间隔触发一次) */
    Event_Sum,                  /* 事件总数 */
    None_Press                  /* 未按下 */
};

/**
 * @brief   按键对象句柄结构体
 */
struct key_handle
{
    uint16_t tick;                                          	  /* 按键系统时间片 */
    uint8_t repeat_cnt     : 4;                             	  /* 按键短按次数 */
    uint8_t event   	   : 4;                             	  /* 触发事件 */
    uint8_t state          : 3;                             	  /* 按键状态 */
    uint8_t debounce_tick  : 3;                             	  /* 消抖时间片 */
    uint8_t active_level   : 1;                                   /* 按键有效按下电平 */
    uint8_t key_level      : 1;                             	  /* 按键引脚当前电平 */
    uint8_t (* pin_read)(void);                         	      /* 获取按键引脚电平 */
    void (* event_callback[Event_Sum])(struct key_handle* key);   /* 按键事件回调函数 */
    struct key_handle* next;                                      /* 单向链表next指针 */
};
typedef struct key_handle *key_handle_t;

/* 按键管理函数接口 */
int8_t key_init(struct key_handle *key, uint8_t (*gpio_pin_read)(void), uint8_t active_level);
int8_t key_handle_register(struct key_handle *key);
int8_t key_handle_detach(struct key_handle *key);
int8_t key_event_callback_register(struct key_handle *key, uint8_t event, void (* event_callback)(key_handle_t key));
void key_tick(void);

#ifdef __cplusplus
}
#endif
#endif /* __KEY_MANAGE_H */

